Надо сделать отдельно для каждого отеля. Причем посмотреть на ключевые слова в негативной и позитивной частях отзыва. На существительные и прилагательные
## udpipe тоже лемматизирует (но хуже, чем mystem) и определяет части речи
data_all_unnest = data_all_unnest %>% rownames_to_column() %>% rename(doc_id = rowname)
data_all_unnest = data_all_unnest %>% filter(doc_id != "3282") %>% filter(doc_id != "3454") %>% filter(doc_id != "3278")
anno1 <- udpipe(data_all_unnest, "russian-gsd")
anno = anno1 %>% filter(token != "отель") %>%
filter(token != "номер") %>%
filter(token != "завтрак") %>%
filter(token != "персонал") %>%
filter(token != "хороший") %>%
filter(token != "отличный") %>%
filter(token != "день") %>%
filter(token != "сделать") %>%
filter(token != "наш") %>%
filter(token != "видимо") # По идее надо было бы удлалить и санкт петербург питер
# filter(token != "санкт") %>%
# filter(token != "петербург") %>%
# filter(token != "питер")
anno$token = gsub("душа", "душ", anno$token)
anno = anno %>% filter(doc_id != "3282") %>% filter(doc_id != "3454") %>% filter(doc_id != "3278")
anno$doc_id = as.character(anno$doc_id)
anno = anno %>% inner_join(data_all_unnest %>% select(doc_id, date, Hotel), by = "doc_id")
# anno$doc_id = as.numeric(anno$doc_id)
anno$text = anno$token
# words_top = anno %>% group_by(token, upos, Hotel) %>% summarise(n = n())
# words_top = words_top[order(words_top$Hotel, words_top$n, decreasing = TRUE),]
# anno %>% distinct(doc_id, .keep_all = T) %>% group_by(Hotel) %>% summarise(n = n()) %>% arrange(-n)
# anno2 = anno %>% count(token) %>% arrange(-n) %>% mutate(n = ifelse(n > quantile(n, .999), NA, n))
kable(anno %>% distinct(doc_id, .keep_all = T) %>% group_by(Hotel) %>% summarise(n = n()) %>% arrange(-n) %>% rename(`Отель` = Hotel, `Кол-во` = n), caption = "<b> Кол-во отзывов с текстом <b>", format = "html") %>% kable_styling(bootstrap_options=c("bordered", "responsive", "striped"), full_width = FALSE) %>% scroll_box(width = "100%", height = "500px")
| Отель | Кол-во |
|---|---|
| Grand europe | 974 |
| Astoria | 691 |
| Lotte | 600 |
| Four seasons | 484 |
| SO | 393 |
| Moika 22 | 368 |
| Wawelberg | 290 |
btm_model <- function(dataframe, name, setseed, number_topics) {
name = name
anno = dataframe
setseed = setseed
k = number_topics
biterms_hotel <- as.data.table(anno[anno$Hotel == name,])
biterms_hotel <- biterms_hotel[, cooccurrence(x = token,
relevant = upos %in% c("NOUN", "ADJ", "VERB") &
nchar(token) > 2 & !token %in% stopwords("ru"),
skipgram = 2),
by = list(doc_id)]
set.seed(setseed)
train <- subset(anno, upos %in% c("NOUN", "ADJ", "VERB") & !token %in% stopwords("ru") & nchar(token) > 2)
train <- train[, c("doc_id", "token")]
set.seed(setseed)
model <- BTM(train, biterms = biterms_hotel, k = k, iter = 2000, background = TRUE, trace = 100)
# biterms_terms = terms(model, type = "biterms")$biterms # нужно только для графика
model
}
# unique(anno$Hotel)
topterms <- function(model, n){
as.data.frame(model$phi) %>%
rownames_to_column() %>%
pivot_longer(cols = -rowname) %>%
group_by(name) %>%
slice_max(value, n = n, with_ties = FALSE) %>%
group_by(name) %>%
mutate(terms=paste(rowname,collapse=', '))
}
text_topic <- function(model, dataframe, name_hotel, topterms_df){
topic_distrib_review = predict(model, dataframe[dataframe$Hotel == name_hotel,]) %>% as.data.frame() %>%
rownames_to_column() %>%
pivot_longer(cols = -rowname)
text_topic = topic_distrib_review %>%
group_by(name) %>%
slice_max(value, n = 10 ,with_ties = FALSE)
data_all_unnest$doc_id = as.character(data_all_unnest$doc_id)
text_topic = inner_join(text_topic, data_all_unnest, by = c("rowname" = "doc_id")) %>% inner_join(topterms_df %>% select(name, terms), by = "name") %>% unique()
text_topic %>% select(Hotel, name, terms, review_text, date)
}
## Функция для каждого корпуса: процент распределение тем в целом в отзывах на каждый отель
## HOTEL | name_topic | percent
topic_distrib <- function(model, name_hotel){
percent = round(model$theta*100, 2)
name = as.data.frame(model$phi) %>% colnames()
d = data.frame(name, percent)
d$Hotel = name_hotel
d %>% select(Hotel, name, percent)
}
## Функция для каждого корпуса: процент распределение тем в целом в отзывах на каждый отель в зависимости от даты
## name_topic | value | percent | date (month)
topic_distrib_date <- function(model, dataframe, name_hotel){
predict(model, dataframe[dataframe$Hotel == name_hotel,]) %>% as.data.frame() %>%
rownames_to_column() %>%
pivot_longer(cols = -rowname)
}
# Для каждой unique даты прогнать функцию
date_topic <- function(df_text, df_unnest, hotel_name, modelBTM){
small_db_general = data.frame()
for (i in 1:length(unique(df_text[df_text$Hotel == hotel_name,]$date))) { # df_unnest = anno, df_text = data_all_unnest
# df_text$date = as.character(df_text$date)
date_my = unique(df_text[df_text$Hotel == hotel_name,]$date)[i]
t = topic_distrib_date(model = modelBTM,
dataframe = df_unnest[df_unnest$Hotel == hotel_name,] %>% filter(date == date_my), name_hotel = hotel_name) %>%
group_by(name) %>%
summarise(value = sum(value)) %>% mutate(per = (round(value/sum(value),4)*100))
t$date = date_my
t = as.data.frame(t)
t$date = as.Date(t$date)
small_db_general = rbind(small_db_general, t)
}
small_db_general
}
distrib_astoria = topic_distrib(model_astoria, name_hotel = "Astoria") %>% mutate(name = str_replace(name, 'V3', 'Работа официантов')) %>% mutate(name = str_replace(name, 'V4', 'Атмосфера ресторан')) %>% mutate(name = str_replace(name, 'V5', 'Работа персонала')) %>% mutate(name = str_replace(name, 'V6', 'Комплимент/акции/скидки')) %>% mutate(name = str_replace(name, 'V8', 'Завтрак')) %>% mutate(name = str_replace(name, 'V9', 'Номер')) %>% mutate(name = str_replace(name, 'V10', 'Стоимость')) %>% mutate(name = str_replace(name, 'V6', 'Сервис')) %>% mutate(name = str_replace(name, 'V7', 'Сервис')) %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>% mutate(name = str_replace(name, 'V2', 'Вид и расположение'))
distrib_astoria$words = unique(text_topic_astoria$terms)
distrib_astoria = distrib_astoria %>% arrange(-percent)
#################################
distrib_wawelberg = topic_distrib(model_wawelberg, name_hotel = "Wawelberg") %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>% mutate(name = str_replace(name, 'V2', 'Стоимость')) %>% mutate(name = str_replace(name, 'V3', 'Номер')) %>% mutate(name = str_replace(name, 'V4', 'Общее впечатление (сервис + интерьер)')) %>% mutate(name = str_replace(name, 'V5', 'Завтрак')) %>% mutate(name = str_replace(name, 'V6', 'Дети')) %>% mutate(name = str_replace(name, 'V7', 'Недостатки')) %>% mutate(name = str_replace(name, 'V8', 'Работа персонала')) %>% mutate(name = str_replace(name, 'V9', 'Трудно интерпретировать тему'))
distrib_wawelberg$words = unique(text_topic_wawelberg$terms)
distrib_wawelberg = distrib_wawelberg %>% arrange(-percent)
###############################
distrib_four = topic_distrib(model_four, name_hotel = "Four seasons") %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Сервис и расположение')) %>% mutate(name = str_replace(name, 'V3', 'Номер')) %>%
mutate(name = str_replace(name, 'V4', 'Работа персонала и бронирование')) %>% mutate(name = str_replace(name, 'V5', 'Недостатки')) %>%
mutate(name = str_replace(name, 'V6', 'Спа')) %>% mutate(name = str_replace(name, 'V7', 'Трудно интерпретировать тему')) %>%
mutate(name = str_replace(name, 'V8', 'Ресторан'))
distrib_four$words = unique(text_topic_four$terms)
distrib_four = distrib_four %>% arrange(-percent)
##############################
distrib_lotte = topic_distrib(model_lotte, name_hotel = "Lotte") %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Спа')) %>% mutate(name = str_replace(name, 'V3', 'Недостатки')) %>%
mutate(name = str_replace(name, 'V4', 'Умный дом')) %>% mutate(name = str_replace(name, 'V5', 'Уровень сервиса и обслуживания')) %>%
mutate(name = str_replace(name, 'V6', 'Вид и расположение')) %>% mutate(name = str_replace(name, 'V7', 'Ресторан')) %>%
mutate(name = str_replace(name, 'V8', 'Работа персонала')) %>% mutate(name = str_replace(name, 'V9', 'Номер'))
distrib_lotte$words = unique(text_topic_lotte$terms)
distrib_lotte = distrib_lotte %>% arrange(-percent)
##############################
distrib_europe = topic_distrib(model_europe, name_hotel = "Grand europe") %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Расположение')) %>% mutate(name = str_replace(name, 'V3', 'Работа персонала')) %>%
mutate(name = str_replace(name, 'V4', 'Стоимость')) %>% mutate(name = str_replace(name, 'V5', 'Вид и достопримечательности')) %>%
mutate(name = str_replace(name, 'V6', 'Расположение')) %>% mutate(name = str_replace(name, 'V7', 'Спа')) %>%
mutate(name = str_replace(name, 'V8', 'Ресторан'))
distrib_europe$words = unique(text_topic_europe$terms)
distrib_europe = distrib_europe %>% arrange(-percent)
##############################
distrib_moika = topic_distrib(model_moika, name_hotel = "Moika 22") %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Ресторан')) %>% mutate(name = str_replace(name, 'V3', 'Расположение')) %>%
mutate(name = str_replace(name, 'V4', 'Работа персонала')) %>% mutate(name = str_replace(name, 'V5', 'Трудно интерпретировать тему')) %>% mutate(name = str_replace(name, 'V6', 'Номер')) %>% mutate(name = str_replace(name, 'V7', 'Недостатки')) %>% mutate(name = str_replace(name, 'V8', 'Вид'))
distrib_moika$words = unique(text_topic_moika10$terms)
distrib_moika = distrib_moika %>% arrange(-percent)
##############################
distrib_so = topic_distrib(model_so, name_hotel = "SO") %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Расположение')) %>% mutate(name = str_replace(name, 'V3', 'Заказ в номер')) %>%
mutate(name = str_replace(name, 'V4', 'Номер')) %>% mutate(name = str_replace(name, 'V5', 'Стоимость')) %>%
mutate(name = str_replace(name, 'V6', 'Недостатки')) %>% mutate(name = str_replace(name, 'V7', 'Спа и ванная комната')) %>%
mutate(name = str_replace(name, 'V8', 'Комплимент/акции/скидки'))
distrib_so$words = unique(text_topic_so$terms)
distrib_so = distrib_so %>% arrange(-percent)
distrib_all = rbind(distrib_astoria, distrib_wawelberg, distrib_four,distrib_europe, distrib_lotte,distrib_moika, distrib_so) %>% mutate(percent = paste0(percent, "%"))
distrib_all %>%
datatable(colnames = c('Отель' = 2, 'Топик' = 3, 'Процент внутри отзывов' = 4, 'Характерные слова' = 4), filter = 'top', options = list(pageLength=10, scrollX='400px', scrollY='350px'))
date_topic_astoria = date_topic(df_text = data_all_unnest, df_unnest = anno, hotel_name = "Astoria", modelBTM = model_astoria)
date_topic_astoria = date_topic_astoria %>% mutate(name = str_replace(name, 'V2', 'Работа официантов')) %>% mutate(name = str_replace(name, 'V3', 'Атмосфера ресторан')) %>% mutate(name = str_replace(name, 'V4', 'Работа персонала')) %>% mutate(name = str_replace(name, 'V5', 'Комплимент/акции/скидки')) %>% mutate(name = str_replace(name, 'V7', 'Завтрак')) %>% mutate(name = str_replace(name, 'V8', 'Номер')) %>% mutate(name = str_replace(name, 'V9', 'Стоимость')) %>% mutate(name = str_replace(name, 'V6', 'Сервис')) %>% mutate(name = str_replace(name, 'V10', 'Вид и расположение')) %>% mutate(name = str_replace(name, 'V1', 'Преимущества'))
date_topic_wawelberg = date_topic(df_text = data_all_unnest, df_unnest = anno, hotel_name = "Wawelberg", modelBTM = model_wawelberg)
date_topic_wawelberg = date_topic_wawelberg %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>% mutate(name = str_replace(name, 'V2', 'Стоимость')) %>% mutate(name = str_replace(name, 'V3', 'Номер')) %>% mutate(name = str_replace(name, 'V4', 'Общее впечатление (сервис + интерьер)')) %>% mutate(name = str_replace(name, 'V5', 'Завтрак')) %>% mutate(name = str_replace(name, 'V6', 'Дети')) %>% mutate(name = str_replace(name, 'V7', 'Недостатки')) %>% mutate(name = str_replace(name, 'V8', 'Работа персонала')) %>% mutate(name = str_replace(name, 'V9', 'Трудно интерпретировать тему'))
date_topic_four = date_topic(df_text = data_all_unnest, df_unnest = anno, hotel_name = "Four seasons", modelBTM = model_four)
date_topic_four = date_topic_four %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Сервис и расположение')) %>% mutate(name = str_replace(name, 'V3', 'Номер')) %>%
mutate(name = str_replace(name, 'V4', 'Работа персонала и бронирование')) %>% mutate(name = str_replace(name, 'V5', 'Недостатки')) %>%
mutate(name = str_replace(name, 'V6', 'Спа')) %>% mutate(name = str_replace(name, 'V7', 'Трудно интерпретировать тему')) %>%
mutate(name = str_replace(name, 'V8', 'Ресторан'))
date_topic_lotte = date_topic(df_text = data_all_unnest, df_unnest = anno, hotel_name = "Lotte", modelBTM = model_lotte)
date_topic_lotte = date_topic_lotte %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Спа')) %>% mutate(name = str_replace(name, 'V3', 'Недостатки')) %>%
mutate(name = str_replace(name, 'V4', 'Умный дом')) %>% mutate(name = str_replace(name, 'V5', 'Уровень сервиса и обслуживания')) %>%
mutate(name = str_replace(name, 'V6', 'Вид и расположение')) %>% mutate(name = str_replace(name, 'V7', 'Ресторан')) %>%
mutate(name = str_replace(name, 'V8', 'Работа персонала')) %>% mutate(name = str_replace(name, 'V9', 'Номер'))
date_topic_europe = date_topic(df_text = data_all_unnest, df_unnest = anno, hotel_name = "Grand europe", modelBTM = model_europe)
date_topic_europe = date_topic_europe %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Расположение')) %>% mutate(name = str_replace(name, 'V3', 'Работа персонала')) %>%
mutate(name = str_replace(name, 'V4', 'Стоимость')) %>% mutate(name = str_replace(name, 'V5', 'Вид и достопримечательности')) %>%
mutate(name = str_replace(name, 'V6', 'Расположение')) %>% mutate(name = str_replace(name, 'V7', 'Спа')) %>%
mutate(name = str_replace(name, 'V8', 'Ресторан'))
date_topic_moika = date_topic(df_text = data_all_unnest, df_unnest = anno, hotel_name = "Moika 22", modelBTM = model_moika)
date_topic_moika = date_topic_moika %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Ресторан')) %>% mutate(name = str_replace(name, 'V3', 'Расположение')) %>%
mutate(name = str_replace(name, 'V4', 'Работа персонала')) %>% mutate(name = str_replace(name, 'V5', 'Трудно интерпретировать тему')) %>% mutate(name = str_replace(name, 'V6', 'Номер')) %>% mutate(name = str_replace(name, 'V7', 'Недостатки')) %>% mutate(name = str_replace(name, 'V8', 'Вид'))
date_topic_so = date_topic(df_text = data_all_unnest, df_unnest = anno, hotel_name = "SO", modelBTM = model_so)
date_topic_so = date_topic_so %>% mutate(name = str_replace(name, 'V1', 'Преимущества')) %>%
mutate(name = str_replace(name, 'V2', 'Расположение')) %>% mutate(name = str_replace(name, 'V3', 'Заказ в номер')) %>%
mutate(name = str_replace(name, 'V4', 'Номер')) %>% mutate(name = str_replace(name, 'V5', 'Стоимость')) %>%
mutate(name = str_replace(name, 'V6', 'Недостатки')) %>% mutate(name = str_replace(name, 'V7', 'Спа и ванная комната')) %>%
mutate(name = str_replace(name, 'V8', 'Комплимент/акции/скидки'))
plot_ly(date_topic_astoria,
x = ~date, y = ~per, type = 'bar', color = ~name, colors = "Paired" ) %>%
layout(title = "Распределение тем внутри отзывов по месяцам (Астория)", font=list(size = 10), barmode = 'stack', xaxis = list(title = "Месяц отзывов",
titlefont = list(size = 10)), yaxis = list(title = "Процент",
titlefont = list(size = 10))) %>%
config(displayModeBar = FALSE)
plot_ly(date_topic_wawelberg,
x = ~date, y = ~per, type = 'bar', color = ~name, colors = "Paired" ) %>%
layout(title = "Распределение тем внутри отзывов по месяцам (Wawelberg)", font=list(size = 10), barmode = 'stack', xaxis = list(title = "Месяц отзывов",
titlefont = list(size = 10)), yaxis = list(title = "Процент",
titlefont = list(size = 10))) %>%
config(displayModeBar = FALSE)
plot_ly(date_topic_four,
x = ~date, y = ~per, type = 'bar', color = ~name, colors = "Paired" ) %>%
layout(title = "Распределение тем внутри отзывов по месяцам (Four Seasons)", font=list(size = 10), barmode = 'stack', xaxis = list(title = "Месяц отзывов",
titlefont = list(size = 10)), yaxis = list(title = "Процент",
titlefont = list(size = 10))) %>%
config(displayModeBar = FALSE)
plot_ly(date_topic_lotte,
x = ~date, y = ~per, type = 'bar', color = ~name, colors = "Paired" ) %>%
layout(title = "Распределение тем внутри отзывов по месяцам (Lotte)", font=list(size = 10), barmode = 'stack', xaxis = list(title = "Месяц отзывов",
titlefont = list(size = 10)), yaxis = list(title = "Процент",
titlefont = list(size = 10))) %>%
config(displayModeBar = FALSE)
plot_ly(date_topic_europe,
x = ~date, y = ~per, type = 'bar', color = ~name, colors = "Paired" ) %>%
layout(title = "Распределение тем внутри отзывов по месяцам (Grand Europe)", font=list(size = 10), barmode = 'stack', xaxis = list(title = "Месяц отзывов",
titlefont = list(size = 10)), yaxis = list(title = "Процент",
titlefont = list(size = 10))) %>%
config(displayModeBar = FALSE)
plot_ly(date_topic_so,
x = ~date, y = ~per, type = 'bar', color = ~name, colors = "Paired" ) %>%
layout(title = "Распределение тем внутри отзывов по месяцам (SO)", font=list(size = 10), barmode = 'stack', xaxis = list(title = "Месяц отзывов",
titlefont = list(size = 10)), yaxis = list(title = "Процент",
titlefont = list(size = 10))) %>%
config(displayModeBar = FALSE)
plot_ly(date_topic_moika,
x = ~date, y = ~per, type = 'bar', color = ~name, colors = "Paired" ) %>%
layout(title = "Распределение тем внутри отзывов по месяцам (Moika 22)", font=list(size = 10), barmode = 'stack', xaxis = list(title = "Месяц отзывов",
titlefont = list(size = 10)), yaxis = list(title = "Процент",
titlefont = list(size = 10))) %>%
config(displayModeBar = FALSE)
# # удаляю строки, где нет данных впринципе и нет текстовых отзывов
# data_all = data %>% filter(!is.na(review_negative)|!is.na(review_positive)) # 294 отзыва
#
# data_all = data %>% select(review_text, date, Hotel)
# data_all = rbind(data_all, data_yandex %>% select(review_text, date, Hotel))
#
# # удаляю строки, где нет данных впринципе и нет текстовых отзывов
# data_all = data_all %>% filter(!is.na(review_text)) # 294 отзыва
# data_all$length = str_count(data_all$review_text, "\\W+") + 1
# data_all = data_all %>% filter(!is.na(length))
#
# data_all = data_all %>%
# rownames_to_column() %>% rename(id = rowname)
#
# data_all$review_text = str_replace_all(data_all$review_text, '\n', ' ')
#
# data_all$lem = system2("/Users/annakostrova/Downloads/mystem", c("-l", "-d", "-e", "utf-8", "-c"), input = data_all$review_text, stdout = TRUE)
#
# data_all_unnest = data_all %>% tidytext::unnest_tokens(lemma, lem)
#
# # Очищаю данные
# data_all_unnest = data_all_unnest %>%
# filter(!str_detect(lemma, '[[:digit:]]')) %>% # цифры
# filter(!str_detect(lemma, "[^\\s]*[0-9][^\\s]*")) %>% #цифры между какими-то символами
# filter(!str_detect(lemma, '[[:punct:]]+')) %>% #пцнктуация
# filter(!str_detect(lemma, "[a-z]")) # английские слова
#
# # Загрузка стоп-слов
# russtopword = data.frame(words = c(stopwords::stopwords("ru"), "это", "в", "с", "и", "который", "свой", "весь", "хотя", "вообще", "т д", "ох", "очень", "европа", "гранд", "астория", "бельмонд", "кемпински", "вавельберг", "антон", "диана", "антоненко", "лотте", "мойка", "видимо", "наш", "также"),stringsAsFactors = FALSE)
#
# # Удаляю стоп-слова
# data_all_unnest = data_all_unnest %>%
# dplyr::filter(!lemma %in% russtopword$words)
#
# data_all_unnest$length = nchar(data_all_unnest$lemma)
# data_all_unnest = data_all_unnest %>% filter(length >2)
#
# data_all_unnest = data_all_unnest %>%
# group_by(id) %>%
# summarise(text = paste0(lemma, collapse=" "))
#
# data_all_unnest = data_all_unnest %>% inner_join(data_all, by = "id") %>% select(-lem)
# unique(data_all_unnest$Hotel)
# write_csv(data_all_unnest, "~/PycharmProjects/pythonProject/data_all_unnest2.csv")